#ifndef SCRIPTRUNNER_H
#define SCRIPTRUNNER_H

#include <string>
//#include "script_instruction_define.h"
//#include "ScriptAddr.h"
#include "KmyScriptAnchor.h"
#include "IButton.h"
#include "KmyScript.h"
#include "KmyVar.h"
#include "../ITimer.h"
#include "KmyMacroDict.h"
#include <stack>
#include "../KmySceneManager.h"
#include "../KmyIScene.h"
#include "../Node/KmyTextLayer.h"
#include "../KmyIDebug.h"

class ScriptRunner;

typedef void (ScriptRunner::*classFunc)();

class ScriptRunner
{
public:
    ScriptRunner();
    ~ScriptRunner();

    void initialize(KmySceneManager *smr, KmyScript *start_scp, KmyScript *macro_dict);
    void finalize();
    /** 脚本循环 */
    void logic();

    static const int EXECUTE_RESULT_ORIG = 1;
    static const int EXECUTE_RESULT_MACRO = 2;
    static const int EXECUTE_RESULT_STACK = 3;
    static const int EXECULT_RESULT_PARAM = 4;

    /** 执行指令
      * 判断是不是指令或宏
      *   是 执行||否 进栈（string
      * 宏的话调用callMacro
      * 指令的话。。。。
      * 返回值-1时指令执行失败
      */
    int execute(const string &instruction);
    /** call带返回 */
    void call(KmyScriptAnchor *ksa);
    /** jump不带返回 */
    void jump(KmyScriptAnchor *ksa);
    void callMacro(int macro);
    void endMacro();

    void wait(int w_time);
    void waitCancel();

    static const int SCRIPT_RESULT_SUCCESS  = 0;
    static const int SCRIPT_RESULT_RETURN   = 1;
    static const int SCRIPT_RESULT_FAIL     = 2;

//    void onPressUp();
//    void onPressDown();
//    void onPressLeft();
//    void onPressRight();
//    const static int KEY_UP = 0x01;
//    const static int KEY_DOWN = 0x02;
//    const static int KEY_LEFT = 0x04;
//    const static int KEY_RIGHT = 0x08;
//    void onPressCross(int key);
//    void onPressButtonA();
//    void onPressButtonB();
//    void onPressButtonX();
//    void onPressButtonY();
//    void onPressButtonSelect();
//    void onPressButtonStart();
//    void onPressButtonL();
//    void onPressButtonR();
//    void onTouch(int x, int y);

private:
    KmyIDebug *debuger;
//    /**
//      事件相应方法脚本，存成变量指针
//      */
    KmyScriptAnchor* cross_up_func;
    KmyScriptAnchor* cross_down_func;
    KmyScriptAnchor* cross_left_func;
    KmyScriptAnchor* cross_right_func;

    KmyScriptAnchor* button_A_func;   // O        A
    KmyScriptAnchor* button_B_func;   // X        B
    KmyScriptAnchor* button_X_func;   // tri      X
    KmyScriptAnchor* button_Y_func;   // rect     Y
    KmyScriptAnchor* button_SELECT_func;
    KmyScriptAnchor* button_START_func;
    KmyScriptAnchor* button_L_func;
    KmyScriptAnchor* button_R_func;

//    string* touch_func;

    /** 原始指令 */
    map<string, classFunc> orig_inst_map;

    /** 查找原始指令ID， 不是原始指令则返回0 */
    classFunc getOrigInst(const string &inst_name);
    int IP;
    int RP;
    int DP;

    // TODO 新作一个栈类型
    stack<KmyScriptAnchor*> RStack;
    stack<KmyVar*> DStack;
    map<string, KmyVar*> sys_var;
    void addSystemVar(const string &name, KmyVar* value);
    KmyVar* getSystemVar(const char* name);

    KmySceneManager *scene_manager;
    /**
       要加个buttonlist（屏幕上的图片按钮
      */
    map<string, IButton*> img_btns;

//    int wait_start_time;
    int wait_time; //ms
    // 是否暂停
    bool is_pause;
    // 是否可以按键鼠标跳过
    bool is_canskip;
    // 是否正在响应按键和鼠标
//    bool is_interrupted;

    KmyScript *curscript;
//    KmyMacroDict *macro_dict;
    KmyScript *macro_dict;

    // 内藏系统变量
    bool automode;  //自动模式（文字显示完毕后自动下一句
    bool autoskip;  //快速略过剧情
    bool control_enable; //是否可以控制（按键，触屏
    bool crossbutton_enable;

    KmyTextLayer *cur_textlayer;
    KmyTextLayer *name_textlayer;

    void run();

    int next_type;
    void next();

    // 临时参数列表
    map<string, KmyVar*> param_list;
    void addParam(string &name, KmyVar *value);
    KmyVar* getParam(const char *pname);
    KmyVar* removeParam(const char *pname);
    void clearParamList();
    // 从参数列表获取对应类型的参数, dft_*是默认值
    int getParamInt(const char *pname, int dft_i);
    float getParamFloat(const char *pname, float dft_f);
    u8* getParamString(const char *pname);

    //宏参数列表
    map<string, KmyVar*>macro_param_list;
    void addMacroParam(string &name, KmyVar *value);
    KmyVar* getMacroParam(const char *pname);
    void clearMacroParamList();

//    void store();
//    void fetch();
    // 原始指令开始

    void eval();  // 执行TJS脚本

/** 系统指令 */
    //    void autowc();  // 自动窗口
    void clearsysvar();  // 清除所有系统变量
    void close();   // 关闭窗口
//    void clickskip();  // clickskip设定
//    void cursor();      // 设定鼠标样式
    void hidemessage(); //隐藏消息窗口（UI一并隐藏
    void nextskip();    // 跳到下个选择支
    void quake();       // 画面抖动
    void stopquake();
//    void rclick();      //  右键设定
    void stopscript();   //停止执行脚本
//    void title();
    void WAIT();
    void waitclick();
    void waitmessage();      //等待 字数*单字延迟
    void waitquake();      //等待震动停止

/** layer操作 */
    void animstart();
    void animstop();
    void waitanim();          // 等待动画停止
    void backlay();
//    void copylay();
    void freeimage();   // 擦除一张图
    void image();       // 添加一张图
    void move();
    void stopmove();
    void waitmove();      //等待自动移动完毕
    void trans();       // 画面切换效果
    void stoptrans();
    void waittrans();      //等待画面切换完毕

/** 标签， 跳转 */
    bool is_return;
    void CALL();
    void LINK();
    void endlink();
    void JUMP();
    void RETURN();

/** 文字层操作 */
    void message(); // 单句文字
    void phonetic(); // 注音文字
    void NAME();    // 人名
    u8* phn_text;
//    void ruby();    // 单独注音
    void ruby2();   // 多字注音
    void endruby();   // 注音指令结束
    void clearmessage();      // 清除所有消息层文字
    void linewait();       // 行末等待点击
    void pagewait();       // 页末等待点击
    void clearcurmsg();      // 清除当前消息层
    void setdelay();   // 文字显示速度设定
    void cancelautomode(); //取消自动模式
    void endline();       // 文字换行
    void cancelskip(); //停止快速略过

/** 新加 */
    void addSprite();
    void removeSprite();
    void updateSprite();

    int obj_joinmode;
    int obj_jointime;
    int obj_leavemode;
    int obj_leavetime;
    void joinmode(); // 设定后面对象的入场方式
    void leavemode();   //设定后面对象的离场方式

    int screen_no;
    void targetscreen();   //设定当前屏幕
};

#endif // SCRIPTRUNNER_H
